package Client;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.List;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;


public class AlibabaClient {
	public class Status {

	}

	private enum Action {
		
		 BACKUP_FILE("backupfile", "bf", "Back up a file",createMultipleOption(0)),
		 RESTORE_FILE("restorefile", "rf", "Restore a file",createMultipleOption(1)),
		 BACKUP_DIR("backupdir", "bd", "Back up a directory",createMultipleOption(2)),
		 RESTORE_DIR("restoredir", "rd", "Restore a directory",createMultipleOption(3)),
		 LIST("list", "ls", "List files in a directory" ,createMultipleOption(4)),
		 CHECK("check","ch","Check and validate backup files",createMultipleOption(5)),
		 CREATE_SNAPSHOT("createsnapshot","cs","Create a snapshot for the user files",createMultipleOption(6)),
		 DELETE_SNAPSHOT("deletesnapshot","ds","Delete a specified user files snapshot",createMultipleOption(7)),
		 HELP("help","?","Print usage information",null),
		 ERROR("error","er","erronous usage",null);


		private String name;
		private String shortName;
		private String description;
		private MultipleOptions options;
		
		private Action(String Name, String shortName, String description, MultipleOptions options) {
	            this.name = Name;
	            this.shortName = shortName;
	            this.description = description;
	            this.options = options;
	        }
		private static MultipleOptions createMultipleOption(int action) {
			MultipleOptions mOpt = new MultipleOptions(action);
			return mOpt;
		}
		
		public String getName() {
			return name;
		}
		
		public List<Option> getOptions() {
			return options.getOptions();
		}
	
        
    }
		    
	 protected static void printMainHelp() {
	        System.out.println("Usage: alibaba command [options]");	        
	        System.out.println("Commands:\n");
	        System.out.println("Command name\t\tShort name\tDescription");
	        System.out.println("--------------------------------------------------------------");
	        System.out.println("backupdir\t\tbd\t\tBackup a directory");
	        System.out.println("backupfile\t\tbf\t\tBackup a file");
	        System.out.println("restoredir\t\trd\t\tRestore a directory");
	        System.out.println("restorefile\t\trf\t\tRestore a file");
	        System.out.println("list\t\t\tls\t\tList a directory");
	        System.out.println("checkall\t\tch\t\tCheck and validate backup files");
	        System.out.println("createsnapshot\t\tcs\t\tCreate a snapshot for the user files");
	        System.out.println("deletesnapshot\t\tds\t\tDelete a specified user files snapshot");
	        System.out.println("help\t\t\t?\t\tPrint usage information");
	        
	    }
	 
	 private static boolean handleCommand(String[] args, Action action) throws IOException, Base64DecodingException {
	        
		 CommandLineParser parser = new GnuParser();
	     Options commandOptions = new Options();
	     CommandLine commandLine;
	     HelpFormatter formatter = new HelpFormatter();

	     MyService service = new MyService();
	    
	     for (Option opt : action.getOptions()) {
		        commandOptions.addOption(opt);
	     }
	        
	        try {
	            commandLine = parser.parse(commandOptions, args);
	        } catch (ParseException exp) {
	            System.out.println(exp.getMessage());
	            formatter.printHelp(action.getName(), commandOptions);
	            return false;
	        }

	        String directoryName = commandLine.getOptionValue("dir");
	        String fileName = commandLine.getOptionValue("file");
	        String userName = commandLine.getOptionValue("user");
	        String snapshotID = commandLine.getOptionValue("snapshot");

	        
	        ClientUtils.printOutValue("Directory:", directoryName);
	        ClientUtils.printOutValue("File:" , fileName);
	        ClientUtils.printOutValue("User:" , userName);
	        ClientUtils.printOutValue("Snapshot:" , snapshotID);

	        CommandParameters commandParams = new CommandParameters(fileName, directoryName, userName, snapshotID);
	        
	        switch(action) {

	        case BACKUP_FILE:
	            return service.backupFile(commandParams);
	        case RESTORE_FILE:
	            return service.restoreFile(commandParams);
	        case BACKUP_DIR:
	            return service.backupDir(commandParams);
	        case RESTORE_DIR:
	            return service.restoreDir(commandParams);
	        case LIST:
	            return service.listDir(commandParams);
	        case CHECK:
	            return service.checkDir(commandParams);
	        case CREATE_SNAPSHOT:
	            return service.createSnapshot(commandParams);
	        case DELETE_SNAPSHOT:
	            return service.deleteSnapshot(commandParams);
	        default:
	            return false;

	        }
	    }
   
	 

	protected static Action parseAction(String[] args){
	    	String commandString = args[0];
	    	if (commandString.equals("backupfile")
	                || commandString.equals("bf")) {
	            return Action.BACKUP_FILE;
	        } else if (commandString.equals("backupdir")
	                || commandString.equals("bd")) {
	            return Action.BACKUP_DIR;
	        } else if (commandString.equals("restorefile")
	                || commandString.equals("rf")) {
	            return Action.RESTORE_FILE;
	        } else if (commandString.equals("restoredir")
	                || commandString.equals("rd")) {
	            return Action.RESTORE_DIR;
	        } else if (commandString.equals("list")
	                || commandString.equals("ls")) {
	            return Action.LIST;
	        } else if (commandString.equals("check")
	                || commandString.equals("ch")) {
	            return Action.CHECK;
	        } else if (commandString.equals("createsnapshot")
	                || commandString.equals("cs")) {
	            return Action.CREATE_SNAPSHOT;
	        } else if (commandString.equals("deletesnapshot")
	                || commandString.equals("ds")) {
	            return Action.DELETE_SNAPSHOT;
	        } else if (commandString.equals("help") || commandString.equals("?")) {
	            return Action.HELP;
	        }
	        else {
	            return Action.ERROR;
	        }
	    }
	 
	 
	 private static boolean doCommand(String[] args) throws Exception {

		 Action action = parseAction(args);
		 if (action == Action.ERROR) {
	           System.out.println("Input error. Type 'help' for usage");
	           return false;
	     }
		 String[] cmdArgs = new String[args.length - 1];
		 System.arraycopy(args, 1, cmdArgs, 0, args.length - 1);

		 switch (action) {
			 case BACKUP_FILE:
		     case RESTORE_FILE:
		     case BACKUP_DIR:
		     case RESTORE_DIR:
		     case LIST:
		     case CHECK:
		     case CREATE_SNAPSHOT:
		     case DELETE_SNAPSHOT:
		    	 return handleCommand(cmdArgs, action);
			   
			 case HELP:
		            printMainHelp();
		            return false;

			 default:
				 System.out.println("Not implememented");
				 return false;
		 }
	 }
	 
	

	 /**
	 * @param args
	 * @throws Exception 
	 */
	 public static void main(String[] args) throws Exception {
		 if (args.length == 0) {
	         System.out.println("Type 'alibaba help' for usage");
	         System.exit(-1);
	     }
	     try {
	        if (doCommand(args)){
	        	System.out.println("Action complete!");
	        }
	     } catch (MalformedURLException e) {
	         e.printStackTrace();
	         System.out.println("An exception occurred while processing the command. The results are inpredictable.");
	     } catch (IOException e) {
	         e.printStackTrace();
	         System.out.println("An exception occurred while processing the command. The results are inpredictable.");
	     }
	     return; 
	 }
	}

